include(['PClass', 'shapes.Line'], 

function(){
	
	declare('shapes.Mesh');
	
	Mesh = PClass.create({
		_meshdata  : null,
		_area      : 0,
		last       : null,
		active     : false,
		_boundingBox      : {min:{x:0, y:0}, max:{x:0,y:0}},
		init: function(){
			this._meshdata = [];
			for(var i=0; i < arguments.length; i++)
				this.push(arguments[i]);
		},
		intersects : function( point, tolerance ){
			var hit = false;
			this.eachTriangle(function(tri){
				hit = tri.intersects(point, tolerance);
				return hit;
			});
			if( hit )
				return [this];
			return null;
		},
		area : function(){
			return this._area;
		},
		meshData : function(){
			return this._meshdata;
		},
		push : function(point){
			this._meshdata.push(point);
		},	
		boundingBox : function(){
			var points = this.meshData();
			var bb = {min:{x:10000, y:10000}, max:{x:-10000,y:-10000}};
			var min = bb.min;
			var max = bb.max;
			for(var i=0; i < points.length; i++){
				var p = points[i];
				if( p.x < min.x ) min.x = p.x
				if( p.x > max.x ) max.x = p.x
				if( p.y < min.y ) min.y = p.y
				if( p.y > max.y ) max.y = p.y			
			}
			return bb;
		},
		setActive : function(value){
			this.active = true;
			if(!value){
				this._stash = null;
			}
		},
		translate : function(x,y){
			for(var i=0; i < this._meshdata.length; i++){
				this._meshdata[i].plusEq({x:x, y:y});
			}
		},
		save : function(){
			if(!this._stash) this._stash = [];
			var backup = [];
			for(var i =0; i < this._meshdata.length; i++){
				backup[i] = {};
				backup[i].x = this._meshdata[i].x;
				backup[i].y = this._meshdata[i].y;
			}
			this._stash.push(backup);
		},
		restore : function(){
			if(this._stash){
				var backup = this._stash.pop();
				for(var i=0; i < backup.length; i++)
					this._meshdata[i].reset(backup[i].x, backup[i].y);
			}
		},
		render : function(gw){
			var c = gw.c;
			c.beginPath();
			var points = this.meshData();
			var p = points[0];
			c.moveTo(p.x | 0, p.y | 0);
			for(var i=0; i < points.length; i++){
				var index = (i+1)%points.length;
				p = points[index];
				c.lineTo(p.x | 0, p.y | 0);
			}
		},
		lines : function(){
			var results = [];
			for(var i=0; i < this._meshdata.length; i++){
				var next = (i+1) % this._meshdata.length;
				results.push(new Line(this._meshdata[i], this._meshdata[next]));
			}
			return results;
		},
		eachTriangle : function( callback ){
			var data = this._meshdata;
			var len = data.length;
			var p1 = data[0];
			var y = 1 % len;
			var z = 2 % len;
			var triangle = new Triangle(p1,data[y],data[z]);
			if( callback(triangle) ){
				return;
			}
			while( z < len ){
				y = z;
				z++;
				
				triangle.set(0, p1);
				triangle.set(1, data[y]);
				triangle.set(2, data[z%len]);
				if( callback(triangle) )
					return;
			}		
		},	
		set : function(index, point){
			this._meshdata[index] = point;
		},
		move : function(x, y){
			this.restore();
			this.save();
			for(var i=0; i < this._meshdata.length; i++){
				var p = this._meshdata[i];
				p.reset(p.x + x, p.y + y);
			}
		},
		setParent : function(){}
	}, 'Mesh');
});